package cn.kgc.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import cn.kgc.base.SystemConstant;
import cn.kgc.entity.Resume;
import cn.kgc.entity.SysParams;
import cn.kgc.excpetion.GraceException;
import cn.kgc.feign.ResumeFeignClient;
import cn.kgc.grace.result.GraceJSONResult;
import cn.kgc.grace.result.ResponseStatusEnum;
import cn.kgc.mapper.SysParamsMapper;
import cn.kgc.service.ResumeService;
import cn.kgc.service.SysParamsService;
import cn.kgc.utils.RedisUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author example
 * @version 1.0
 */
@Slf4j
@Service("sysParamsService")
@SuppressWarnings("all")
public class SysParamsServiceImpl extends ServiceImpl<SysParamsMapper, SysParams> implements SysParamsService {
    @Resource
    private RedisUtil redisUtil;

    @Resource
    private RedissonClient redissonClient;

    @Resource
    private ResumeService resumeService;

    @Resource
    private ResumeFeignClient resumeFeignClient;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean refreshResume(String resumeId, String userId) {
        //1 判断用户当前简历的刷新次数
        String key="RESUME_REFRESH_COUNT_"+userId+"_"+resumeId;
        int count= redisUtil.get(key)==null? 0:Integer.parseInt(redisUtil.get(key).toString());
        int maxRefshCount= (int) getRefreshMaxCount();
        if(count>maxRefshCount){
            //如果用户刷新简历次数大于最大次数,抛出异常
            GraceException.display(ResponseStatusEnum.RESUME_MAX_LIMIT_ERROR);
        }
        //用户的刷新次数+1
        count++;
        //将最新的次数保存到缓存中
        redisUtil.set(key,count,1,TimeUnit.DAYS);
        //2 刷新简历(更新简历的刷新时间)
        LambdaUpdateWrapper<Resume> updateWrapper=new LambdaUpdateWrapper<>();
        updateWrapper.set(Resume::getRefreshTime,new Date());
        updateWrapper.eq(Resume::getId,resumeId);
        updateWrapper.eq(Resume::getUserId,userId);
        boolean flag=  resumeService.update(updateWrapper);
        if(flag) {
            //3 将简历保存到ES中
            Object object = resumeFeignClient.refreshResume(resumeId, userId);
            GraceJSONResult graceJSONResult = JSONUtil.toBean(JSONUtil.toJsonStr(object), GraceJSONResult.class);
            if (graceJSONResult.getStatus() != 200 || graceJSONResult.getSuccess() == false) {
                GraceException.display(ResponseStatusEnum.RESUME_REFRESH_ERROR);
            }
        }
        return true;
    }

    @Override
    public Object getRefreshMaxCount() {
        //如果缓存中有数据,从缓存中返回数据
        Object cacheValue=  redisUtil.get("maxResumeRefreshCounts");
        if(cacheValue!=null){
            return cacheValue;
        }
        //如果缓存中没有数据获得锁
        RLock lock = redissonClient.getLock("maxResumeRefreshCountsLock");
        //判断请求是否获得锁
        boolean isLock=false;
        try {
            //将请求锁定10秒,如果请求1秒还没有获得锁
            isLock= lock.tryLock(1,10, TimeUnit.SECONDS);
            if(!isLock) {
                //直接返回默认值(每个用户每天允许最大刷新次数为5)。
                return SystemConstant.MAX_RESUME_REFRESH_COUNTS;
            }
            //如果请求得到了锁,在次从缓存中获得数据,如果此时缓存中有数据直接返回数据
            cacheValue= redisUtil.get("maxResumeRefreshCounts");
            if(cacheValue!=null){
                return cacheValue;
            }
            //如果缓存中没有数据,从数据库中获得数据
            List<SysParams> lists = list();
            //如果数据库中没有数据,将系统默认的最大刷新次数保存到缓存中
            if(CollUtil.isEmpty(lists)){
                //每个用户每天允许最大刷新次数为保存到缓存中
                redisUtil.set(
                    "maxResumeRefreshCounts",
                    SystemConstant.MAX_RESUME_REFRESH_COUNTS,
                    SystemConstant.MAX_RESUME_REFRESH_COUNTS_CACHE_TIME,
                    TimeUnit.DAYS
                );
                //返回简历允许的最大刷新次数
                return SystemConstant.MAX_RESUME_REFRESH_COUNTS;
            }
            //如果数据库中有数据,将数据保存到缓存中
            SysParams sysParams = lists.get(0);
            redisUtil.set(
                    "maxResumeRefreshCounts",
                    sysParams.getMaxResumeRefreshCounts(),
                    SystemConstant.MAX_RESUME_REFRESH_COUNTS_CACHE_TIME,
                    TimeUnit.DAYS
            );
            //返回简历允许的最大刷新次数
            return sysParams.getMaxResumeRefreshCounts();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }finally{
            if(isLock && lock.isHeldByCurrentThread()){
                lock.unlock();
            }
        }
    }

    @Override
    public void modifySysParams(int maxCount) {
        //获得表中的数据
        try {
            List<SysParams> list = list();
            if (list.size() == 1) {
                //如果表中有数据,更新表中的数据
                SysParams sysParams = list.get(0);
                sysParams.setMaxResumeRefreshCounts(maxCount);
                updateById(sysParams);
            } else {
                //如果表中没有数据,新增数据
                SysParams sysParams = new SysParams();
                sysParams.setMaxResumeRefreshCounts(maxCount);
                save(sysParams);
            }
            //将最大刷新次数保存到缓存中
            redisUtil.delete("maxResumeRefreshCounts");
        }catch(Exception e){
            //将消息发送消息队列中,从消息队列中获得数据在从缓存中删除
            redisUtil.delete("maxResumeRefreshCounts");
        }
    }
}